package com.pingan.haofang.searchcloud.quartz.service;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.pingan.haofang.searchcloud.common.constants.Constants;
import com.pingan.haofang.searchcloud.index.constants.IndexBuildOperation;
import com.pingan.haofang.searchcloud.index.constants.IndexBuildRunType;
import com.pingan.haofang.searchcloud.index.constants.IndexBuildStatus;
import com.pingan.haofang.searchcloud.index.constants.IndexBuildType;
import com.pingan.haofang.searchcloud.index.constants.IndexDataSourceType;
import com.pingan.haofang.searchcloud.index.dto.IndexBuildIncDTO;
import com.pingan.haofang.searchcloud.index.dto.IndexBuildProgressDTO;
import com.pingan.haofang.searchcloud.index.service.IndexBuildProgressService;
import com.pingan.haofang.searchcloud.index.service.IndexBuildService;
import com.pingan.haofang.searchcloud.indexdatasource.dto.IndexDatasourceDTO;
import com.pingan.haofang.searchcloud.quartz.dto.ArgsDto;
import com.pingan.haofang.searchcloud.quartz.dto.ScheduleTask;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.Scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

import static com.pingan.haofang.searchcloud.index.constants.IndexBuildConstants.ARGS;
import static com.pingan.haofang.searchcloud.index.constants.IndexBuildConstants.IS_RESUME_JOB;
import static com.pingan.haofang.searchcloud.index.constants.IndexBuildConstants.RESUME_JOB;

/**
 * 索引基准构建执行器
 *
 * @author LUYI374
 * @date 2017年5月9日
 * @since 1.0.0
 */
@Component
public class IndexBuildScheduleExecution {

    private static final Logger LOG = LoggerFactory.getLogger(IndexBuildScheduleExecution.class);

    private static final Gson GSON = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();

    @Autowired
    private IndexBuildService indexBuildService;

    @Autowired
    private IndexBuildProgressService indexBuildProgressService;

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private ScheduleTaskManager scheduleTaskManager;

    /**
     * @param task
     * @param progressId
     * @param indexDatasourceList
     * @param jobExecutionContext
     */
    public void execute(ScheduleTask task, long progressId, List<IndexDatasourceDTO> indexDatasourceList,
                        JobExecutionContext jobExecutionContext) {

        final String resumeJob = jobExecutionContext.getMergedJobDataMap().getString(RESUME_JOB);

        //删除JobDataMap中的RESUME_JOB
        jobExecutionContext.getTrigger().getJobDataMap().remove(RESUME_JOB);
        jobExecutionContext.getMergedJobDataMap().remove(RESUME_JOB);

        final boolean isResumeJob;
        if (IS_RESUME_JOB.equals(resumeJob)) {
            isResumeJob = true;
        } else {
            isResumeJob = false;
        }

        if (jobExecutionContext.isRecovering() || isResumeJob) {

            JobDetail jobDetail = jobExecutionContext.getJobDetail();
            String argsStr = jobDetail.getJobDataMap().getString(ARGS);
            ScheduleTask recoveringTask = GSON.fromJson(argsStr, ScheduleTask.class);
            progressId = recoveringTask.getArgs().getProgressId();
            LOG.info("this is a recoveringJob use progressId from quartz, progressId: {}", progressId);
        }

        IndexBuildProgressDTO progress = null;
        if (progressId > 0) {
            progress = indexBuildProgressService.query(progressId);

            //恢复的任务需要将计数重置
            progress.setFetchSuccessCount(0L);
            progress.setFetchTotalCount(0L);
            progress.setImportSuccessCount(0L);
            progress.setImportTotalCount(0L);

        } else {
            progress = new IndexBuildProgressDTO();
            if (CollectionUtils.isNotEmpty(indexDatasourceList)) {
                progress.setConfigSnapshot(JSON.toJSONString(indexDatasourceList));
            }
            progress.setIndexBuildType(IndexBuildType.FULL.value);
            progress.setIndexName(task.getName());
            progress.setProjectCode(task.getGroup());
            progress.setRunType(IndexBuildRunType.CRON.value);
            progress.setStatus(IndexBuildStatus.TODO.value);
            progress.setStartTime(new Date());
            indexBuildProgressService.updateProgress(progress);
        }
        MDC.put(Constants.REQUEST_ID, String.valueOf(progress.getId()));
        LOG.info("schedule task start, group:{}, name:{}, desc:{}, progressId:{}, dataSource:{}", task.getGroup(),
                task.getName(), task.getDesc(), progress.getId(), indexDatasourceList.toString());

        indexBuildService.executeIndexBuild(progress, true, indexDatasourceList, jobExecutionContext, isResumeJob);

        LOG.info("schedule task end, index progress info:{}", progress);
        MDC.clear();
    }

    public void executeInc(ScheduleTask task, long progressId, ArgsDto argsDto,
                           JobExecutionContext jobExecutionContext) {

        //定时增量 ，check锁
        if (indexBuildService.checkLock(argsDto.getProjectCode(), argsDto.getIndexName())) {
            LOG.info("lock exist,inc schedule task be paused, group:{}, name:{},desc:{}, progressId:{}",
                    task.getGroup(),
                    task.getName(), task.getDesc(), progressId);
            return;
        }

        for (IndexDatasourceDTO indexDatasourceDTO : argsDto.getIndexDatasourceList()) {
            //过滤出带增量的数据源，遍历拉取
            if (IndexDataSourceType.NOT_SURPPORT.getValue() != indexDatasourceDTO.getIncDatasourceType()
                    && null != indexDatasourceDTO.getIncDatasourceRpc()) {

                LOG.info("inc schedule task start, group:{}, name:{}, desc:{}, progressId:{}, dataSource:{}",
                        task.getGroup(),
                        task.getName(), task.getDesc(), progressId, indexDatasourceDTO.getName());
                IndexBuildIncDTO indexBuildIncDTO = new IndexBuildIncDTO();
                indexBuildIncDTO.setContent(null);
                indexBuildIncDTO.setDataSourceName(indexDatasourceDTO.getName());
                indexBuildIncDTO.setOperation(IndexBuildOperation.SAVE.value);
                indexBuildIncDTO.setIndexName(argsDto.getIndexName());
                indexBuildIncDTO.setProjectCode(argsDto.getProjectCode());
                indexBuildIncDTO.setTimestamp(System.currentTimeMillis());

                indexBuildService.executeIndexInc(indexBuildIncDTO);
            }
        }
    }


}
